import { 
  Component, 
  OnInit, 
  OnDestroy, 
  ViewChild, 
  ElementRef, 
  AfterViewInit,
  ChangeDetectorRef,
  NgZone
} from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
import { Subscription } from 'rxjs';

import { CodeDataService } from '../../services/code-data.service';
import { SyntaxHighlightService } from '../../services/syntax-highlight.service';
import { VirtualScrollService, VirtualScrollState } from '../../services/virtual-scroll.service';
import { 
  CodeViewerData, 
  CodeRegion, 
  ProcessedLine, 
  DisplayLine,
  VirtualDisplayLine,
  LineVisibility, 
  LineType 
} from '../../models/code-content.interface';

@Component({
  selector: 'app-virtual-code-viewer',
  standalone: true,
  imports: [CommonModule, RouterModule],
  templateUrl: './virtual-code-viewer.component.html',
  styleUrls: ['./virtual-code-viewer.component.scss']
})
export class VirtualCodeViewerComponent implements OnInit, OnDestroy, AfterViewInit {
  @ViewChild('scrollContainer', { static: false }) scrollContainer!: ElementRef<HTMLDivElement>;
  @ViewChild('contentContainer', { static: false }) contentContainer!: ElementRef<HTMLDivElement>;

  // 数据相关
  codeData: CodeViewerData | null = null;
  loading = true;
  error: string | null = null;
  processedLines: ProcessedLine[] = [];
  displayLines: VirtualDisplayLine[] = [];

  // 虚拟滚动相关
  virtualState: VirtualScrollState | null = null;
  renderedLines: VirtualDisplayLine[] = [];
  enableVirtualScroll = true;
  virtualScrollThreshold = 1000; // 超过1000行启用虚拟滚动
  
  // 行高测量相关
  private itemHeightCache = new Map<number, number>();
  private measureElement: HTMLDivElement | null = null;
  private defaultLineHeight = 24;
  
  // 订阅
  private subscriptions: Subscription[] = [];

  constructor(
    private codeDataService: CodeDataService,
    private syntaxHighlightService: SyntaxHighlightService,
    private virtualScrollService: VirtualScrollService,
    private sanitizer: DomSanitizer,
    private cdr: ChangeDetectorRef,
    private ngZone: NgZone
  ) {}

  ngOnInit(): void {
    this.loadCodeData();
    this.createMeasureElement();
  }

  ngAfterViewInit(): void {
    this.initializeVirtualScroll();
  }

  ngOnDestroy(): void {
    this.cleanup();
  }

  private async loadCodeData(): Promise<void> {
    try {
      this.codeDataService.getCodeData().subscribe({
        next: (data) => {
          this.codeData = data;
          this.processCodeContent();
          this.loading = false;
          
          // 检查是否需要启用虚拟滚动
          this.checkVirtualScrollNeed();
          
          if (this.enableVirtualScroll) {
            this.setupVirtualScroll();
          }
          
          this.cdr.detectChanges();
        },
        error: (error) => {
          console.error('加载代码数据失败:', error);
          this.error = '加载代码数据失败，请稍后重试';
          this.loading = false;
        }
      });
    } catch (error) {
      console.error('请求代码数据时发生错误:', error);
      this.error = '请求数据时发生错误';
      this.loading = false;
    }
  }

  private processCodeContent(): void {
    if (!this.codeData) return;

    const lines = this.codeData.fileContent.content.split('\n');
    this.processedLines = [];
    this.displayLines = [];

    // 创建行状态映射
    const lineVisibilityMap = new Map<number, { 
      visibility: LineVisibility; 
      regionId?: string; 
      lineType: LineType;
      backgroundColor?: string;
    }>();

    // 标记原始可见区域
    this.codeData.visibleRegions.forEach((region, index) => {
      for (let i = region.startLine; i <= region.endLine; i++) {
        lineVisibilityMap.set(i, {
          visibility: LineVisibility.VISIBLE,
          regionId: region.id || `region-${index}`,
          lineType: LineType.ORIGINAL_VISIBLE,
          backgroundColor: region.backgroundColor
        });
      }
    });

    // 处理每一行
    lines.forEach((content, index) => {
      const lineNumber = index + 1;
      const lineInfo = lineVisibilityMap.get(lineNumber);

      this.processedLines.push({
        lineNumber,
        content,
        visibility: lineInfo?.visibility || LineVisibility.HIDDEN,
        lineType: lineInfo?.lineType,
        regionId: lineInfo?.regionId,
        backgroundColor: lineInfo?.backgroundColor
      });
    });

    // 生成显示行数组
    this.generateDisplayLines();
  }

  private generateDisplayLines(): void {
    this.displayLines = [];
    let virtualIndex = 0;
    let i = 0;

    while (i < this.processedLines.length) {
      const line = this.processedLines[i];
      
      if (line.visibility === LineVisibility.VISIBLE) {
        // 可见行直接添加，并应用语法高亮
        const highlightedContent = this.syntaxHighlightService.highlightCode(
          line.content, 
          this.codeData?.fileContent.language || 'typescript'
        );

        this.displayLines.push({
          virtualIndex: virtualIndex++,
          lineNumber: line.lineNumber,
          content: line.content,
          highlightedContent: highlightedContent,
          lineType: line.lineType,
          backgroundColor: line.backgroundColor
        });
        i++;
      } else {
        // 找到连续的隐藏行区域
        const hiddenStart = i;
        while (i < this.processedLines.length && this.processedLines[i].visibility === LineVisibility.HIDDEN) {
          i++;
        }
        const hiddenEnd = i - 1;
        const hiddenCount = hiddenEnd - hiddenStart + 1;
        
        // 添加折叠占位符
        this.displayLines.push({
          virtualIndex: virtualIndex++,
          lineNumber: this.processedLines[hiddenStart].lineNumber,
          content: `// ··· ${hiddenCount} 行被折叠 ···`,
          isCollapsedPlaceholder: true,
          hiddenLineStart: this.processedLines[hiddenStart].lineNumber,
          hiddenLineEnd: this.processedLines[hiddenEnd].lineNumber,
          regionBefore: hiddenStart > 0 ? this.processedLines[hiddenStart - 1].regionId : undefined,
          regionAfter: hiddenEnd < this.processedLines.length - 1 ? this.processedLines[hiddenEnd + 1].regionId : undefined
        });
      }
    }
  }

  private checkVirtualScrollNeed(): void {
    this.enableVirtualScroll = this.displayLines.length > this.virtualScrollThreshold;
    console.log(`虚拟滚动状态: ${this.enableVirtualScroll ? '启用' : '禁用'} (${this.displayLines.length} 行)`);
  }

  private initializeVirtualScroll(): void {
    if (!this.enableVirtualScroll || !this.scrollContainer) {
      return;
    }

    // 设置虚拟滚动容器
    this.virtualScrollService.setScrollElement(this.scrollContainer.nativeElement);

    // 订阅虚拟滚动状态
    const stateSubscription = this.virtualScrollService.getState().subscribe(state => {
      this.virtualState = state;
      this.updateRenderedLines();
      this.cdr.detectChanges();
    });

    this.subscriptions.push(stateSubscription);
  }

  private setupVirtualScroll(): void {
    if (!this.enableVirtualScroll) {
      return;
    }

    // 预测行高并初始化虚拟滚动
    this.measureDefaultHeight();
    
    this.virtualScrollService.initialize({
      itemHeight: this.defaultLineHeight,
      containerHeight: 600, // 默认高度，会被ResizeObserver更新
      buffer: 5,
      overscan: 10,
      enableDynamicHeight: true,
      scrollDebounceTime: 16
    }, this.displayLines.length);

    // 初始化后测量实际行高
    setTimeout(() => {
      this.measureActualHeights();
    }, 100);
  }

  private updateRenderedLines(): void {
    if (!this.virtualState || !this.enableVirtualScroll) {
      this.renderedLines = this.displayLines;
      return;
    }

    this.renderedLines = this.displayLines.slice(
      this.virtualState.renderStartIndex,
      this.virtualState.renderEndIndex + 1
    );

    // 更新渲染偏移
    this.renderedLines.forEach((line, index) => {
      line.renderOffset = this.virtualState!.offsetY;
      line.isVisible = index >= (this.virtualState!.visibleStartIndex - this.virtualState!.renderStartIndex) &&
                      index <= (this.virtualState!.visibleEndIndex - this.virtualState!.renderStartIndex);
    });
  }

  private createMeasureElement(): void {
    this.measureElement = document.createElement('div');
    this.measureElement.style.position = 'absolute';
    this.measureElement.style.visibility = 'hidden';
    this.measureElement.style.whiteSpace = 'pre';
    this.measureElement.style.font = '14px "Courier New", monospace';
    this.measureElement.className = 'code-line';
    document.body.appendChild(this.measureElement);
  }

  private measureDefaultHeight(): void {
    if (!this.measureElement) return;

    this.measureElement.textContent = 'const example = "test";';
    this.defaultLineHeight = this.measureElement.offsetHeight || 24;
  }

  private measureActualHeights(): void {
    if (!this.enableVirtualScroll || !this.measureElement) return;

    const heightMap = new Map<number, number>();

    // 测量前50行的实际高度
    const samplesToMeasure = Math.min(50, this.displayLines.length);
    
    for (let i = 0; i < samplesToMeasure; i++) {
      const line = this.displayLines[i];
      const height = this.measureLineHeight(line);
      heightMap.set(i, height);
      this.itemHeightCache.set(i, height);
    }

    // 更新虚拟滚动服务
    this.virtualScrollService.setItemHeights(heightMap);
  }

  private measureLineHeight(line: VirtualDisplayLine): number {
    if (!this.measureElement) return this.defaultLineHeight;

    if (line.isCollapsedPlaceholder) {
      this.measureElement.textContent = line.content;
      this.measureElement.className = 'collapsed-line';
    } else {
      this.measureElement.innerHTML = line.highlightedContent || line.content;
      this.measureElement.className = 'code-line';
    }

    const height = this.measureElement.offsetHeight;
    return height || this.defaultLineHeight;
  }

  // 展开折叠区域
  expandHiddenRegion(startLine: number, endLine: number, virtualIndex: number): void {
    const linesToExpand = this.processedLines.slice(startLine - 1, endLine);
    
    // 更新processedLines中的可见性
    linesToExpand.forEach(line => {
      line.visibility = LineVisibility.VISIBLE;
      line.lineType = LineType.MANUALLY_EXPANDED;
      line.backgroundColor = undefined;
    });

    // 重新生成显示行
    this.generateDisplayLines();

    // 如果启用虚拟滚动，更新虚拟滚动状态
    if (this.enableVirtualScroll) {
      this.virtualScrollService.updateItemCount(this.displayLines.length);
      
      // 重新测量新展开行的高度
      setTimeout(() => {
        this.measureNewExpandedLines(virtualIndex, linesToExpand.length);
      }, 50);
    }

    this.cdr.detectChanges();
  }

  private measureNewExpandedLines(startIndex: number, count: number): void {
    if (!this.enableVirtualScroll) return;

    const heightMap = new Map<number, number>();
    
    for (let i = 0; i < count; i++) {
      const lineIndex = startIndex + i;
      if (lineIndex < this.displayLines.length) {
        const line = this.displayLines[lineIndex];
        const height = this.measureLineHeight(line);
        heightMap.set(lineIndex, height);
        this.itemHeightCache.set(lineIndex, height);
      }
    }

    this.virtualScrollService.setItemHeights(heightMap);
  }

  // 向上展开5行
  expandUpward(startLine: number, endLine: number, virtualIndex: number): void {
    const expandCount = 5;
    const expandEnd = endLine;
    const expandStart = Math.max(startLine, endLine - expandCount + 1);
    
    if (expandEnd >= expandStart) {
      this.expandHiddenRegion(expandStart, expandEnd, virtualIndex);
    }
  }

  // 向下展开5行
  expandDownward(startLine: number, endLine: number, virtualIndex: number): void {
    const expandCount = 5;
    const expandStart = startLine;
    const expandEnd = Math.min(endLine, startLine + expandCount - 1);
    
    if (expandEnd >= expandStart) {
      this.expandHiddenRegion(expandStart, expandEnd, virtualIndex);
    }
  }

  // 展开所有隐藏行
  expandAll(): void {
    this.processedLines.forEach(line => {
      if (line.visibility === LineVisibility.HIDDEN) {
        line.visibility = LineVisibility.VISIBLE;
        line.lineType = LineType.MANUALLY_EXPANDED;
        line.backgroundColor = undefined;
      }
    });

    this.generateDisplayLines();

    if (this.enableVirtualScroll) {
      this.virtualScrollService.updateItemCount(this.displayLines.length);
      setTimeout(() => {
        this.measureActualHeights();
      }, 100);
    }

    this.cdr.detectChanges();
  }

  // 重置显示
  collapseAll(): void {
    if (!this.codeData) return;
    this.processCodeContent();
    
    if (this.enableVirtualScroll) {
      this.virtualScrollService.updateItemCount(this.displayLines.length);
    }
    
    this.cdr.detectChanges();
  }

  // 滚动到指定行
  scrollToLine(lineNumber: number): void {
    const lineIndex = this.displayLines.findIndex(line => line.lineNumber === lineNumber);
    
    if (lineIndex >= 0) {
      if (this.enableVirtualScroll) {
        this.virtualScrollService.scrollToIndex(lineIndex, 'center');
      } else {
        // 传统滚动方式
        const element = this.scrollContainer?.nativeElement.querySelector(`[data-line="${lineNumber}"]`);
        if (element) {
          element.scrollIntoView({ behavior: 'smooth', block: 'center' });
        }
      }
    }
  }

  // 切换虚拟滚动
  toggleVirtualScroll(): void {
    this.enableVirtualScroll = !this.enableVirtualScroll;
    
    if (this.enableVirtualScroll) {
      this.setupVirtualScroll();
      this.initializeVirtualScroll();
    } else {
      this.virtualScrollService.cleanup();
      this.renderedLines = this.displayLines;
    }
    
    this.cdr.detectChanges();
  }

  // 获取显示的行数组
  getDisplayLines(): VirtualDisplayLine[] {
    return this.enableVirtualScroll ? this.renderedLines : this.displayLines;
  }

  // 获取容器样式
  getContainerStyle(): any {
    if (!this.enableVirtualScroll || !this.virtualState) {
      return {};
    }

    return {
      height: `${this.virtualState.totalHeight}px`,
      position: 'relative'
    };
  }

  // 获取内容样式
  getContentStyle(): any {
    if (!this.enableVirtualScroll || !this.virtualState) {
      return {};
    }

    return {
      transform: `translateY(${this.virtualState.offsetY}px)`,
      position: 'absolute',
      top: 0,
      left: 0,
      right: 0
    };
  }

  // 获取可见区域信息
  getVisibleRegions(): CodeRegion[] {
    return this.codeData?.visibleRegions || [];
  }

  // 重新加载数据
  reloadData(): void {
    this.loading = true;
    this.error = null;
    this.loadCodeData();
  }

  // 获取文件信息
  getFileInfo(): string {
    if (!this.codeData) return '';
    return `${this.codeData.fileContent.filename} (${this.codeData.fileContent.totalLines} 行)`;
  }

  // 检查是否支持语法高亮
  isSyntaxHighlightSupported(): boolean {
    if (!this.codeData) return false;
    return this.syntaxHighlightService.isSupportedLanguage(this.codeData.fileContent.language);
  }

  // 安全地处理高亮后的HTML内容
  getSafeHtml(content: string): SafeHtml {
    return this.sanitizer.bypassSecurityTrustHtml(content);
  }

  // 获取当前语言
  getCurrentLanguage(): string {
    return this.codeData?.fileContent.language || 'typescript';
  }

  // 获取性能信息
  getPerformanceInfo(): string {
    if (!this.enableVirtualScroll) {
      return `传统渲染模式 - ${this.displayLines.length} 行全部渲染`;
    }

    if (!this.virtualState) {
      return '虚拟滚动初始化中...';
    }

    const renderedCount = this.virtualState.renderEndIndex - this.virtualState.renderStartIndex + 1;
    const visibleCount = this.virtualState.visibleEndIndex - this.virtualState.visibleStartIndex + 1;
    
    return `虚拟滚动模式 - 渲染 ${renderedCount}/${this.displayLines.length} 行 (可见 ${visibleCount} 行)`;
  }

  // TrackBy函数优化性能
  trackByLine(index: number, line: VirtualDisplayLine): any {
    return line.virtualIndex;
  }

  private cleanup(): void {
    this.subscriptions.forEach(sub => sub.unsubscribe());
    this.virtualScrollService.cleanup();
    
    if (this.measureElement) {
      document.body.removeChild(this.measureElement);
      this.measureElement = null;
    }
  }
} 